/**************
 * GT9147通过IIC通讯,为了与其他屏幕驱动芯片兼容，接口引脚标注与GT9147无关
 * CT_SCL    IIC时钟     PB0
 * CT_SDA    IIC数据     PF11
 * CT_RST    复位        PC13
 * CT_INT    触摸中断    PB1
 * all setting default
*****************/
#define DEBUG_PrintInfo

#include "Drv_GT9147.h"
#include "Drv_NT35510.h"
#include "BitBand.h"
#include "Drv_TIM.h"
#ifdef DEBUG_PrintInfo
#include "stdio.h"
#endif

#define CT_RST           PCout(13)
#define CT_INT           PBin(1)
#define CT_IIC_SCL       PBout(0)
#define CT_IIC_SDA       PFout(11) //SDA	 
#define CT_READ_SDA      PFin(11)  //输入SDA 

#define CT_SDA_IN()     {GPIOF->MODER&=~(3<<(2*11));GPIOF->MODER|=0<<2*11;}	//PF11输入模式
#define CT_SDA_OUT()    {GPIOF->MODER&=~(3<<(2*11));GPIOF->MODER|=1<<2*11;} 	//PF11输出模式
#define CT_Delay(x)     delay_US(x)


#define SIMU_IIC
#ifdef  SIMU_IIC

void IIC_Init()
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  GPIO_InitStruct.Pin = CT_SCL_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(CT_SCL_GPIO_Port, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = GPIO_PIN_11;
  HAL_GPIO_Init(CT_SDA_GPIO_Port, &GPIO_InitStruct);
  
  CT_IIC_SDA = 1;	  	  
	CT_IIC_SCL = 1;
}

void IIC_Start()
{
	CT_SDA_OUT(); //  sda线输出
	CT_IIC_SDA = 1;	  	  
	CT_IIC_SCL = 1;
	CT_Delay(30);
 	CT_IIC_SDA = 0; // START:when CLK is high,DATA change form high to low 
	CT_Delay(5);
	CT_IIC_SCL = 0; // 钳住I2C总线，准备发送或接收数据 
}

void IIC_Stop()
{
	CT_SDA_OUT(); // sda线输出
	CT_IIC_SCL = 1;
	CT_Delay(30);
	CT_IIC_SDA = 0; // STOP:when CLK is high DATA change form low to high
	CT_Delay(5);
	CT_IIC_SDA = 1; // 发送I2C总线结束信号  
}

// 1: Failed 0: success
uint8_t IIC_WaitAck()
{
	uint32_t ucErrTime=0;

	CT_SDA_IN(); //SDA设置为输入  
	CT_IIC_SDA = 1;	   
	CT_IIC_SCL = 1;
	CT_Delay(5);
	while(CT_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime > 250)
		{
			IIC_Stop();
			return 1;
		} 
		CT_Delay(5);
	}
	CT_IIC_SCL = 0; //时钟输出0

	return 0;  
}

void IIC_Ack()
{
	CT_IIC_SCL = 0;
	CT_SDA_OUT();
	CT_Delay(5);
	CT_IIC_SDA = 0;
	CT_Delay(5);
	CT_IIC_SCL = 1;
	CT_Delay(5);
	CT_IIC_SCL = 0;
}

void IIC_NAck()
{
	CT_IIC_SCL = 0;
	CT_SDA_OUT();
	CT_Delay(5);
	CT_IIC_SDA = 1;
	CT_Delay(5);
	CT_IIC_SCL = 1;
	CT_Delay(5);
	CT_IIC_SCL = 0;
}

void IIC_SendByte(uint8_t byte)
{
  uint32_t i;   

	CT_SDA_OUT(); 	    
  CT_IIC_SCL = 0; // 拉低时钟开始数据传输
	CT_Delay(5);
	for(i = 0; i < 8; i++)
  {              
    CT_IIC_SDA = (byte &0x80) >> 7;
    byte <<= 1; 	      
		CT_IIC_SCL = 1; 
		CT_Delay(5);
		CT_IIC_SCL = 0;	
		CT_Delay(5);
  }	 
}

// ack = 0: NAck 1: Ack
uint8_t IIC_ReadByte(uint8_t ack)
{
	uint32_t i;
  uint8_t byte_recv = 0;

 	CT_SDA_IN(); // SDA设置为输入
	CT_Delay(30);
	for(i = 0; i < 8; i++)
	{ 
		CT_IIC_SCL = 0; 	    	   
		CT_Delay(5);
		CT_IIC_SCL = 1;	 
		byte_recv <<= 1;
		if(CT_READ_SDA)
      byte_recv++;   
	}	  				 
	if (!ack)
    IIC_NAck(); // 发送nACK
	else
    IIC_Ack();  // 发送ACK  

 	return byte_recv;
}

#endif


//I2C读写命令	
#define GT_CMD_WR 		0X28     	//写命令
#define GT_CMD_RD 		0X29		  //读命令
//#define GT_CMD_WR 		0xBA
//#define GT_CMD_RD 		0xBB

// GT9147 reg
#define GT_CTRL_REG 	0X8040   	//GT9147控制寄存器
#define GT_CFGS_REG 	0X8047   	//GT9147配置起始地址寄存器
#define GT_CHECK_REG 	0X80FF   	//GT9147校验和寄存器
#define GT_PID_REG 		0X8140   	//GT9147产品ID寄存器

#define GT_GSTID_REG 	0X814E   	//GT9147当前检测到的触摸情况
#define GT_TP1_REG 		0X8150  	//第一个触摸点数据地址
#define GT_TP2_REG 		0X8158		//第二个触摸点数据地址
#define GT_TP3_REG 		0X8160		//第三个触摸点数据地址
#define GT_TP4_REG 		0X8168		//第四个触摸点数据地址
#define GT_TP5_REG 		0X8170		//第五个触摸点数据地址  


_m_tp_dev tp_dev;

const uint8_t GT9147_CFG_TBL[] = 
{
  0X60,0XE0,0X01,0X20,0X03,0X05,0X35,0X00,0X02,0X08,
	0X1E,0X08,0X50,0X3C,0X0F,0X05,0X00,0X00,0XFF,0X67,
	0X50,0X00,0X00,0X18,0X1A,0X1E,0X14,0X89,0X28,0X0A,
	0X30,0X2E,0XBB,0X0A,0X03,0X00,0X00,0X02,0X33,0X1D,
	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X32,0X00,0X00,
	0X2A,0X1C,0X5A,0X94,0XC5,0X02,0X07,0X00,0X00,0X00,
	0XB5,0X1F,0X00,0X90,0X28,0X00,0X77,0X32,0X00,0X62,
	0X3F,0X00,0X52,0X50,0X00,0X52,0X00,0X00,0X00,0X00,
	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,
	0X0F,0X03,0X06,0X10,0X42,0XF8,0X0F,0X14,0X00,0X00,
	0X00,0X00,0X1A,0X18,0X16,0X14,0X12,0X10,0X0E,0X0C,
	0X0A,0X08,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
	0X00,0X00,0X29,0X28,0X24,0X22,0X20,0X1F,0X1E,0X1D,
	0X0E,0X0C,0X0A,0X08,0X06,0X05,0X04,0X02,0X00,0XFF,
	0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
	0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
	0XFF,0XFF,0XFF,0XFF
};


//
uint8_t GT9147_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
  uint32_t i;
  uint32_t ret;

  IIC_Start();
  IIC_SendByte(GT_CMD_WR);
  IIC_WaitAck();
  IIC_SendByte(reg >> 8);
  IIC_WaitAck();
  IIC_SendByte(reg &0xFF);
  IIC_WaitAck();
  for(i = 0; i < len; ++i)
  {
    IIC_SendByte(buf[i]);
    ret = IIC_WaitAck();
    if(ret)
      break;
  }
  IIC_Stop();

  return ret;
} 

// 
void GT9147_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
  uint32_t i;

  IIC_Start();
  IIC_SendByte(GT_CMD_WR);
  IIC_WaitAck();
  IIC_SendByte(reg >> 8);
  IIC_WaitAck();
  IIC_SendByte(reg &0xFF);
  IIC_WaitAck();

  IIC_Start();
  IIC_SendByte(GT_CMD_RD);
  IIC_WaitAck();
  for(i = 0; i < len; ++i)
  {
    buf[i] = IIC_ReadByte(i == (len - 1) ?0 :1);
  }
  IIC_Stop();
}

// 配置GT9147, mode: 0，不配置GT9147 flash; 1, 配置9147 flash
uint8_t GT9147_SendCFG(uint8_t mode)
{
  uint8_t buf[2] = {0};
  uint32_t i;

  buf[0] = 0;
  buf[1] = mode;
  // 计算校验和
  for(i = 0; i < sizeof(GT9147_CFG_TBL); ++i)
  {
    buf[0] += GT9147_CFG_TBL[i];
  }

  buf[0] = (~buf[0]) + 1;
  GT9147_WR_Reg(GT_CFGS_REG, (uint8_t*)GT9147_CFG_TBL, sizeof(GT9147_CFG_TBL));
  GT9147_WR_Reg(GT_CHECK_REG, buf, 2); // 校验和， 配置更新标记

  return 0;
}

uint8_t GT9147_Init(void)
{
  uint8_t IDbuf[5] = {0, 0, 0, 0, 0};
  GPIO_InitTypeDef GPIO_InitStruct;

  // GPIO INIT
  GPIO_InitStruct.Pin = CT_INT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(CT_INT_GPIO_Port, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = CT_RST_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  HAL_GPIO_Init(CT_RST_GPIO_Port, &GPIO_InitStruct);

  IIC_Init();
  CT_RST = 0;
  HAL_Delay(10);
  CT_RST = 1;
  HAL_Delay(10);

  GPIO_InitStruct.Pin = CT_INT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(CT_INT_GPIO_Port, &GPIO_InitStruct);

  // read ID
  HAL_Delay(100);
  GT9147_RD_Reg(GT_PID_REG, IDbuf, 4);
  IDbuf[4] = 0;
#ifdef DEBUG_PrintInfo
  printf("CTP ID:%s\n",IDbuf);
#endif
  if((IDbuf[0] == '9') &&(IDbuf[1] == '1') &&(IDbuf[2] == '4') &&(IDbuf[3] == '7'))
  {
    uint8_t tmp;

    tmp = 0x02;
    GT9147_WR_Reg(GT_CTRL_REG, &tmp, 1); // soft reset
    GT9147_RD_Reg(GT_CFGS_REG, &tmp, 1); // 读取flash配置信息版本
#ifdef DEBUG_PrintInfo
    printf("CFG vesion:%d\n",tmp);
#endif
    // GT9147_Send_Cfg(0); // 配置GT9147, 默认不配置
    HAL_Delay(10);
    tmp = 0x00;
    GT9147_WR_Reg(GT_CTRL_REG, &tmp, 1); // soft reset end
    
    tp_dev.screenDir = LCD_DIR;
    tp_dev.sizeWidth = LCD_Size_W;
    tp_dev.sizeHeight = LCD_Size_H;
  }

  return 0;
}

const uint16_t GT9147_TPX_TBL[5] = {GT_TP1_REG,GT_TP2_REG,GT_TP3_REG,GT_TP4_REG,GT_TP5_REG};

// 轮询方式
// mode: 0 nomal mod
// 返回值: 0:当前无触摸, 1:当前有触摸
uint8_t GT9147_Scan(uint8_t mode)
{
  uint32_t i;
  uint8_t tmp;
  uint8_t tmpsta;
  uint8_t buf[4];
  uint8_t touchRes = 0;
  // 进入次数, 通常每10次执行一次检测(cnt_Entry 10~241), 数据异常时次次执行检测(cnt_Entry 0~9)
  static uint8_t cnt_Entry;

  cnt_Entry++;

  if((cnt_Entry%10 == 0) ||(cnt_Entry < 10))
  {
    GT9147_RD_Reg(GT_GSTID_REG, &mode, 1); // 读取触摸点的状态
    if((mode&0x80) &&((mode&0x0F) < 6))
    {
      tmp = 0;
      GT9147_WR_Reg(GT_GSTID_REG, &tmp, 1); // 清标志
    }
    if((mode&0x0F) &&((mode&0x0F) < 6))
    {
      tmp = 0xFF << (mode&0x0F);
      tmpsta = tp_dev.sta;
      tp_dev.sta = (~tmp) |TP_PRES_DOWN |TP_CATH_PRES;
      tp_dev.x[4] = tp_dev.x[0];
      tp_dev.y[4] = tp_dev.y[0];
      for(i = 0; i < 5; ++i)
      {
        if(tp_dev.sta&(1<<i)) // 触摸有效
        {
          GT9147_RD_Reg(GT9147_TPX_TBL[i], buf, 4);
          if(!tp_dev.screenDir) // 横屏
          {
            tp_dev.y[i]=((uint16_t)buf[1]<<8)+buf[0];
						tp_dev.x[i]=tp_dev.sizeWidth-(((uint16_t)buf[3]<<8)+buf[2]);
          }
          else
          {
            tp_dev.x[i]=((uint16_t)buf[1]<<8)+buf[0];
						tp_dev.y[i]=((uint16_t)buf[3]<<8)+buf[2];
          }
#ifdef DEBUG_PrintInfo
            printf("x[%d]:%d,y[%d]:%d\r\n",i,tp_dev.x[i],i,tp_dev.y[i]);
#endif
        }
      }
      touchRes = 1;

      // 误测排除
      if((tp_dev.x[0] > tp_dev.sizeWidth) ||(tp_dev.y[0] > tp_dev.sizeHeight)) // 坐标超出
      {
        if((mode &0x0F) > 1) // 有其他触点数据
        {
          tp_dev.x[0] = tp_dev.x[1];
          tp_dev.y[0] = tp_dev.y[1];
          cnt_Entry = 0; // 误测一次，查询间隔计数清零
        }
        else
        {
          // 还原上次触点数据记录
          tp_dev.x[0]=tp_dev.x[4];
					tp_dev.y[0]=tp_dev.y[4];
          mode = 0x80;
          tp_dev.sta = tmpsta;
        }
      }
      else
      {
        cnt_Entry = 0;
      }
    }
  }
  // 无触点
  if((mode &0x8F) == 0x80) 
  {
    if(tp_dev.sta &TP_PRES_DOWN) // 之前有触点按下
    {
      tp_dev.sta &= ~(1<<7); // 清空按下标记
    }
    else
    {
      tp_dev.x[0]=0xffff;
			tp_dev.y[0]=0xffff;
			tp_dev.sta&=0XE0;	//清除点有效标记	
    }
  }

  if(cnt_Entry > 240)
    cnt_Entry = 10;

  return touchRes;
}
